﻿/*
 * Class for keeping track of the different kinds Cellular Automata theat are used. CaTypeSetup offers a
 * set of helper methods for factoring CA's
 * Author: Anders Høst | ahkj@itu
 * Date: 13 dec. 2010
 */

using System.Collections.Generic;
using System.Runtime.CompilerServices;
using AutomaTones.Model.Automaton_Model;
using AutomaTones.Model.Automaton_Model.RuleLib;

namespace AutomaTones.Model.Tools {
    public enum CAType {
        OneDimensional = 1, TwoDimensional, TwoDimensionalEXT, GameOfLife, GameOfLifeEXT, Off
    }

    public class CaTypeSetup
    {
        [MethodImpl(MethodImplOptions.Synchronized)]
        public static void SetupGameOfLife(ref CellularAutomaton ca, int xSize, int ySize, uint states, State[,] config) {
            //in case grid is not _rectangular, choose the shortest side
            ca = GameOfLife.SetupGameOfLife(xSize < ySize ? (uint)xSize : (uint)ySize, states);
            for (int i = 0; i < xSize; i++) {
                for (int j = 0; j < ySize; j++) {
                    ca[i, j] = config[i, j].CurrentState;
                }
            }
        }

       /// <summary>
       /// Sets up a CA as one dimensional. Also know from WolframTones.
       /// </summary>
   //   private void SetUpOneDimensionalCA() {
   //       var int[]
   //
   //
   //       int[] sta = new int[rules.Count];
   //       int[] pat = new int[rules.Count];
   //       foreach (State[,] rule in rules) {
   //           for (int i = 0; i < rule.GetLength(0); i++) {
   //
   //           }
   //       }
   //   }

        /// <summary>
        /// Setting up a two-dimensional user defined CA. 
        /// </summary>
        /// <param name="ca"></param>
        /// <param name="rules"></param>
        /// <param name="centerCell"></param>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public static void SetupTwoDimensional(ref CellularAutomaton ca, List<State[,]> rules, uint statespace, uint dimension, State[,] grid)
       {
           int[] pat = new int[rules.Count * 8];
           int[] stat = new int[rules.Count];
           int position = 0;
           for(int rule = 0; rule < rules.Count; rule++){
               //cell state around center 1,2,3,4,5,6,7,8
               if (rules[rule][0, 0].CurrentState > 2 && statespace == 2)
                   rules[rule][0, 0].CurrentState = 2;
              pat[position] = rules[rule][0, 0].CurrentState; position++;

              if (rules[rule][1, 0].CurrentState > 2 && statespace == 2)
                  rules[rule][1, 0].CurrentState = 2;
              pat[position] = rules[rule][1, 0].CurrentState; position++;

              if (rules[rule][2, 0].CurrentState > 1 && statespace == 2)
                  rules[rule][2, 0].CurrentState = 1;
              pat[position] = rules[rule][2, 0].CurrentState; position++;

              if (rules[rule][2, 1].CurrentState > 1 && statespace == 2)
                  rules[rule][2, 1].CurrentState = 1;
              pat[position] = rules[rule][2, 1].CurrentState; position++;

              if (rules[rule][2, 2].CurrentState > 1 && statespace == 2)
                  rules[rule][2, 2].CurrentState = 1;
              pat[position] = rules[rule][2, 2].CurrentState; position++;

              if (rules[rule][1, 2].CurrentState > 1 && statespace == 2)
                  rules[rule][1, 2].CurrentState = 1;
              pat[position] = rules[rule][1, 2].CurrentState; position++;

              if (rules[rule][0, 2].CurrentState > 1 && statespace == 2)
                  rules[rule][0, 2].CurrentState = 1;
              pat[position] = rules[rule][0, 2].CurrentState; position++;

              if (rules[rule][0, 1].CurrentState >  1 && statespace == 2)
                  rules[rule][0, 1].CurrentState = 1;
              pat[position] = rules[rule][0, 1].CurrentState; position++;

              if (rules[rule][1, 1].CurrentState > 1 && statespace == 2)
                  rules[rule][1, 1].CurrentState = 1;
               stat[rule] = rules[rule][1, 1].CurrentState;
           }
           ca = WolframAutomata.NewPatternAutomaton(dimension, pat, stat, 8, statespace);
           for (int i = 0; i < dimension; i++) {
               for (int j = 0; j < dimension; j++) {
                   ca[i, j] = grid[i, j].CurrentState;
               }
           }
        }
    }
}
